package net.guerlab.sdk.anubis.request;

import java.util.LinkedHashMap;
import java.util.Map;

import org.apache.commons.lang3.RandomUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import net.guerlab.sdk.anubis.AnubisException;
import net.guerlab.sdk.anubis.accesstoken.AccessTokenManager;
import net.guerlab.sdk.anubis.response.AbstractBusinessResponse;
import net.guerlab.sdk.anubis.sign.SignHelper;

/**
 * 抽象业务请求
 *
 * @author guer
 *
 * @param <T>
 *            响应实体类型
 */
public abstract class AbstractBusinessRequest<T extends AbstractBusinessResponse<?>> extends AbstractRequest<T> {

    private static final Logger LOGGER = LoggerFactory.getLogger(AbstractBusinessRequest.class);

    /**
     * 请求参数
     */
    private Map<String, Object> params = new LinkedHashMap<>(4);

    @Override
    public final void createRequestUri(
            StringBuilder builder,
            String appId,
            String secretKey) {
        createRequestUri(builder);

        String salt = String.valueOf(RandomUtils.nextInt(1000, 10000));

        String data = null;

        try {
            data = objectMapper.writeValueAsString(getReuqestData());
        } catch (Exception e) {
            LOGGER.debug(e.getMessage(), e);
            throw new AnubisException(e.getMessage(), e);
        }

        params.put("app_id", appId);
        params.put("salt", salt);
        params.put("data", data);
        params.put("signature",
                SignHelper.generateBusinessSign(appId, AccessTokenManager.instance().getAccessToken(), salt, data));
    }

    @Override
    public String requestBody() {
        try {
            return objectMapper.writeValueAsString(params);
        } catch (Exception e) {
            LOGGER.debug(e.getMessage(), e);
            throw new AnubisException(e.getMessage(), e);
        }
    }

    /**
     * 构造请求URI
     *
     * @param builder
     *            请求URI构造器
     */
    protected abstract void createRequestUri(
            StringBuilder builder);

    /**
     * 获取请求数据
     *
     * @return 请求数据
     */
    protected abstract Object getReuqestData();

}
